﻿// -------------------- iSharePoint -------------------- //
// 
//  Company:	IT Complex, LLC
//  Project:	Smart.Tests
//  File name:	BaseTests.cs
//  Developer:	Igor Solomatov
//  Created:	20.12.2014
// 
// -------------------- iSharePoint -------------------- //

using System;
using System.Threading;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Smart.Tests
{
	[TestClass]
	public class BaseTests
	{
		private class DisposableTest : Disposable
		{
			public bool Disposed { get; private set; }

			protected override void RealDispose()
			{
				Disposed = true;
			}
		}

		[TestMethod]
		public void TestDisposable()
		{
			var d = new DisposableTest();
			Assert.IsFalse(d.Disposed);
			d.Dispose();
			Assert.IsTrue(d.Disposed);
		}

		[TestMethod]
		public void TestExpirable()
		{
			var t = Environment.TickCount;
			while (t == Environment.TickCount) ;

			var e = new Expirable<string>(100);
			Assert.AreEqual("v1", e.Ensure(() => "v1"));
			Assert.AreEqual("v1", e.Ensure(() => "v2"));

			Thread.Sleep(100);

			t = Environment.TickCount;
			while (t == Environment.TickCount) ;

			Assert.AreEqual("v3", e.Ensure(() => "v3"));
		}

		public class WeakReferenced
		{
			public string V;

			public WeakReferenced(string v)
			{
				V = v;
			}
		}

		private void Collect()
		{
			var reps = 10;
			var size = GC.GetTotalMemory(false);
			var newSize = size;
			do
			{
				GC.WaitForPendingFinalizers();
				GC.Collect();
				size = newSize;
				newSize = GC.GetTotalMemory(false);
			} while (size != newSize || reps-- > 0);
		}

		private void Weak(WeakExpirable<WeakReferenced> l, string expected, string to)
		{
			Assert.AreEqual(expected, l.Ensure(() => new WeakReferenced(to)).V);
		}

		[TestMethod]
		public void TestWeakExpirable()
		{
			var t = Environment.TickCount;
			while (t == Environment.TickCount) ;

			var e = new WeakExpirable<WeakReferenced>(100);
			Assert.AreEqual("v1", e.Ensure(() => new WeakReferenced("v1")).V);
			Assert.AreEqual("v1", e.Ensure(() => new WeakReferenced("v2")).V);

			Thread.Sleep(100);

			t = Environment.TickCount;
			while (t == Environment.TickCount) ;

			Assert.AreEqual("v3", e.Ensure(() => new WeakReferenced("v3")).V);

			var l = new WeakExpirable<WeakReferenced>(10000);

			Weak(l, "v1", "v1");
			Weak(l, "v1", "v2");

			Collect();

			Weak(l, "v3", "v3");
		}
	}
}